package com.github.cakin.shiro.chapter3.permission;

import com.alibaba.druid.util.StringUtils;
import org.apache.shiro.authz.Permission;

import static com.github.cakin.shiro.chapter3.constant.Constant.NUM2;
import static com.github.cakin.shiro.chapter3.constant.Constant.NUM3;

/**
 * @date: 2020/5/17
 * @author: cakin
 * @description: BitPermission 用于实现位移方式的权限
 * <p>
 * +资源字符串+权限位+实例ID
 * 以+开头 中间通过+分割
 * <p>
 * 权限：
 * 0 表示所有权限
 * 1 新增 0001
 * 2 修改 0010
 * 4 删除 0100
 * 8 查看 1000
 * <p>
 * 如 +user+10 表示对资源user拥有修改/查看权限，注意，这里的10是2+8，是代表十进制的
 * <p>
 * 不考虑一些异常情况
 * 深
 */
public class BitPermission implements Permission {
    /**
     * 资源
     */
    private String resourceIdentify;
    /**
     * 权限位
     */
    private int permissionBit;
    /**
     * 实例id
     */
    private String instanceId;

    /**
     * 功能描述：将String类型解析为 BitPermission
     *
     * @param permissionString 权限字符串
     * @author cakin
     * @date 2020/5/17
     */
    public BitPermission( String permissionString ) {
        String[] array = permissionString.split("\\+");

        if (array.length > 1) {
            resourceIdentify = array[1];
        }

        if (StringUtils.isEmpty(resourceIdentify)) {
            resourceIdentify = "*";
        }

        if (array.length > NUM2) {
            permissionBit = Integer.valueOf(array[NUM2]);
        }

        if (array.length > NUM3) {
            instanceId = array[NUM3];
        }

        if (StringUtils.isEmpty(instanceId)) {
            instanceId = "*";
        }
    }

    /**
     * 功能描述：用于判断权限匹配
     *
     * @param p 用户登录时传入的权限
     * @return boolean 鉴权是否成功
     * @author cakin
     * @date 2020/5/17
     * @description: 该函数被触发时刻
     * implies:77, BitPermission (com.github.cakin.shiro.chapter3.permission)
     * isPermitted:469, AuthorizingRealm (org.apache.shiro.realm)
     * isPermitted:462, AuthorizingRealm (org.apache.shiro.realm)
     * isPermitted:457, AuthorizingRealm (org.apache.shiro.realm)
     * isPermitted:223, ModularRealmAuthorizer (org.apache.shiro.authz)
     * isPermitted:113, AuthorizingSecurityManager (org.apache.shiro.mgt)
     * isPermitted:158, DelegatingSubject (org.apache.shiro.subject.support)
     * testIsPermitted:52, AuthorizerTest (com.github.cakin.shiro.chapter3)
     */
    public boolean implies( Permission p ) {
        if (!(p instanceof BitPermission)) {
            return false;
        }
        BitPermission other = (BitPermission) p;
        // 和传入的资源不匹配
        if (!("*".equals(this.resourceIdentify) || this.resourceIdentify.equals(other.resourceIdentify))) {
            return false;
        }
        // 和传入的权限不匹配
        if (!(this.permissionBit == 0 || (this.permissionBit & other.permissionBit) != 0)) {
            return false;
        }
        // 和传入的实例id不匹配
        if (!("*".equals(this.instanceId) || this.instanceId.equals(other.instanceId))) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return "BitPermission{"
                + "resourceIdentify='" + resourceIdentify + '\''
                + ", permissionBit=" + permissionBit
                + ", instanceId='" + instanceId + '\''
                + '}';
    }
}
